home *** CD-ROM | disk | FTP | other *** search
Wrap
Text File | 2000-09-28 | 23.9 KB | 753 lines | [ TEXT/CWIE]
/* File: Scroll Controls Offscreen.c Contains: Sample code illustrating scrolling of controls via an off screen GWorld Written by: Geoff Stahl (ggs) Copyright: Copyright (c) 1999 Apple Computer, Inc., All Rights Reserved. You may incorporate this Apple sample source code into your program(s) without restriction. This Apple sample source code has been provided "AS IS" and the responsibility for its operation is yours. You are not permitted to redistribute this Apple sample source code as "Apple sample source code" after having made changes. If you're going to re-distribute the source, we require that you make it clear in the source that the code was descended from Apple sample source code, but that you've made changes. */ // system includes ---------------------------------------------------------- #include <MacMemory.h> #include <Events.h> #include <Fonts.h> #include <Windows.h> #include <TextEdit.h> #include <Dialogs.h> #include <Sound.h> #include <SoundInput.h> #include <ToolUtils.h> #include <OSUtils.h> #include <Controls.h> #include <Devices.h> #include <LowMem.h> #include <stdlib.h> // project includes --------------------------------------------------------- // statics/globals (internal only) ------------------------------------------ // Menu defs enum { kMenuApple = 128, kMenuFile = 129, kFileQuit = 1, kButtonMenuID = 150 }; enum { // Window Constants kOffScreenHeight = 1600, // self e. kOffScreenWidth = 900, // " kWindowHeight = 400, // " kWindowWidth = 500, // " kWindowOffset = 100, // " // Scroll bar constants kScrollBarWidth = 16, // fixed kScrollArrowWidth = kScrollBarWidth, // " kScrollBarWidthAdjust = kScrollBarWidth - 1, // " kPageOverlap = 10, // overlap for a page down or up kThumbTrackSlop = 100, // delta from scroll bar for snap to start kNumControls = 400 // number of controls }; Rect gRectWindowGbl; // window rectanglein global coordinates ControlHandle ghControls [kNumControls]; // test controls Point gPtCntlPos [kNumControls]; // initial control postions WindowPtr gpWindow = NULL; // main window GWorldPtr gpGWOffScreen = NULL; // main window offscreen scratch short gScrollVThumbSize = 0; short gScrollHThumbSize = 0; short gTotalVSizeAdjust = 0; short gTotalHSizeAdjust = 0; ControlHandle ghHScrollBar = NULL; // main window scroll bar ControlHandle ghVScrollBar = NULL; // main window scroll bar RgnHandle gSaveClip = NULL; // clipping save for control drawing exclusions ControlRef gControl; // active scroll control SInt32 gStartValue; // scroll start value SInt32 gValueSlop; // slop for mouse live scroll calcs SInt32 gSaveValue; // current scroll value on live exit SInt32 gSleepTime = 60; // WaitNextEvent sleep time Boolean gDone = false; // done yet // functions Prototypes (internal/private) ----------------------------------- void CleanUp (void); // clean ups after application void ScrollControls (WindowPtr pWinParent, short left, short top); // moves postion of controls in relation to scrolled positon of window without updating void ScrollDrawContent (WindowPtr pWindow, short wWindowLeft, short wWindowTop); // draws contents from offscreen to on and diretcly draws scroll bar on screen void DoUpdate (WindowPtr pWindow); // draw from off screen to on and updates control postions on screen for events void MoveScroll (ControlHandle hScrollBar, short wDist); // adjust scroll bar cotnrol position accouting for control limits pascal void ProcScroll (ControlHandle hControl, short wPart); // proc to handle clicks in scroll bar gray or arrows (page up/down, line up/down) void EndThumbTracking (void); // handles release of live scroll SInt32 CalcValueFromPoint (ControlHandle hControl, Point thePoint); // converts mouse to scroll postion and handles out of slop area pascal void ProcScrollThumbAction (void); // proc to handle live scrolling OSErr BeginThumbTracking (ControlRef hControl); // handles beginning of live scrolling void DrawOneControlOffscreen (ControlHandle hControl); // updates the image of hControl for offscreen void DoContentClick (WindowPtr pWindow, EventRecord * pEvent); // overall content click handler void DoMenu (SInt32 menuResult); // menu event handler void DoEvent (void); // event handler void DrawOffScreen (CGrafPtr pCGOffScreen); // offscreen update (this would also be called for control value updates) void SetScrollParams (WindowPtr hWindow); // sets scroll bar size reference vars void AdjustScrollBar (WindowPtr pWindow, ControlHandle scrollBar); // sets appearance savvy portional scroll bar up void InitToolbox(void); // standard inits Boolean SetUp (void); // application setup // NOTE: Initial control position is stored in gPtCntlPos Point array to allow reference during scrolling, // functions (internal/private) --------------------------------------------- void CleanUp (void) { MenuHandle hMenu; HideWindow (gpWindow); KillControls (gpWindow); if (gpWindow) DisposeWindow (gpWindow); gpWindow = NULL; if (gpGWOffScreen) DisposeGWorld (gpGWOffScreen); gpGWOffScreen = NULL; hMenu = GetMenu (kButtonMenuID); DeleteMenu (kButtonMenuID); DisposeMenu (hMenu); hMenu = GetMenu (kButtonMenuID); DeleteMenu (kMenuFile); DisposeMenu (hMenu); hMenu = GetMenu (kButtonMenuID); DeleteMenu (kMenuApple); DisposeMenu (hMenu); } // -------------------------------------------------------------------------- void ScrollControls (WindowPtr pWinParent, short left, short top) { Rect rectNull = {0, 0, 0, 0}; GrafPtr pGrafSave; RgnHandle hRgnClipSave; short i; GetPort (&pGrafSave); SetPort ((GrafPtr) pWinParent); // set the clip region to empty to avoid updates hRgnClipSave = NewRgn (); GetClip ( hRgnClipSave ); ClipRect ( &rectNull ); // move controls to support mouse down events in the window for (i = 0; i < kNumControls; i++) if (((gPtCntlPos [i].v - top) != (**ghControls[i]).contrlRect.top) || ((gPtCntlPos [i].h - left) != (**ghControls[i]).contrlRect.left))// move Controls for window pos using top stored in refcon MoveControl (ghControls[i], gPtCntlPos [i].h - left, gPtCntlPos [i].v - top); SetClip (hRgnClipSave); SetPort (pGrafSave); } // -------------------------------------------------------------------------- void ScrollDrawContent (WindowPtr pWindow, short wWindowLeft, short wWindowTop) // offset and draw window content from offscreen to on { Rect rectDest = ((GrafPtr)pWindow)->portRect; Rect rectSource = ((GrafPtr)pWindow)->portRect; GrafPtr pCGrafSave; GetPort (&pCGrafSave); SetPort ((GrafPtr) pWindow); OffsetRect (&rectSource, wWindowLeft, wWindowTop); // offset for position in offscreen rectDest.right -= kScrollBarWidthAdjust; // don't draw scroll bars rectDest.bottom -= kScrollBarWidthAdjust; rectSource.right -= kScrollBarWidthAdjust; rectSource.bottom -= kScrollBarWidthAdjust; CopyBits (&((GrafPtr)gpGWOffScreen)->portBits, &pWindow->portBits, &rectSource, &rectDest, srcCopy, NULL); Draw1Control (ghHScrollBar); // draw scroll bar Draw1Control (ghVScrollBar); // draw scroll bar SetPort (pCGrafSave); } // -------------------------------------------------------------------------- void DoUpdate (WindowPtr pWindow) { ScrollDrawContent (pWindow, GetControlValue (ghHScrollBar), GetControlValue (ghVScrollBar)); // draw content offscreen to on ScrollControls (pWindow, GetControlValue (ghHScrollBar), GetControlValue (ghVScrollBar)); // update controls positions } // -------------------------------------------------------------------------- void MoveScroll (ControlHandle hScrollBar, short wDist) // update thumb position check for ends { short wScrollPos = GetControlValue (hScrollBar); wScrollPos = wScrollPos + wDist; if ( wScrollPos < GetControlMinimum ( hScrollBar ) ) wScrollPos = GetControlMinimum ( hScrollBar ); else if ( wScrollPos > GetControlMaximum ( hScrollBar ) ) wScrollPos = GetControlMaximum ( hScrollBar ); SetControlValue (hScrollBar, wScrollPos); } // -------------------------------------------------------------------------- pascal void ProcScroll (ControlHandle hControl, short wPart) // handle scroll callback { WindowPtr pWindow = (**hControl).contrlOwner; short wScrollDist = 0; switch (wPart) { case kControlIndicatorPart: // scroll up wScrollDist = gStartValue - GetControlValue (hControl); break; case kControlUpButtonPart: // scroll up wScrollDist = -2; break; case kControlDownButtonPart: // scroll down wScrollDist = 2; break; case kControlPageUpPart: // page up if ( hControl == ghHScrollBar) wScrollDist = -(pWindow->portRect.right - pWindow->portRect.left - kPageOverlap); else wScrollDist = -(pWindow->portRect.bottom - pWindow->portRect.top - kPageOverlap); break; case kControlPageDownPart: // page up if ( hControl == ghHScrollBar) wScrollDist = (pWindow->portRect.right - pWindow->portRect.left - kPageOverlap); else wScrollDist = (pWindow->portRect.bottom - pWindow->portRect.top - kPageOverlap); break; } if ((wScrollDist) && (pWindow)) { MoveScroll (hControl, wScrollDist); ScrollDrawContent (pWindow, GetControlValue (ghHScrollBar), GetControlValue (ghVScrollBar)); } } // -------------------------------------------------------------------------- void EndThumbTracking ( void ) // mouse up on thumb determine and set final value { SetClip (gSaveClip); DisposeRgn (gSaveClip); SetControlValue (gControl, gSaveValue); gSaveValue = 0; return; } // -------------------------------------------------------------------------- SInt32 CalcValueFromPoint (ControlHandle hControl, Point thePoint) // figure where we are in scroll bar terms { SInt32 theValue = 0, theRange, theDistance, thePin; Rect rectControl; WindowPtr pWindow; pWindow = (*hControl)->contrlOwner; rectControl = (*hControl)->contrlRect; theRange = GetControlMaximum ( hControl ) - GetControlMinimum ( hControl ); if ( hControl == ghHScrollBar) { // Scroll distance adjusted for scroll arrows and the thumb theDistance = rectControl.right - rectControl.left - gTotalHSizeAdjust; // Pin thePoint to the middle of the thumb thePin = rectControl.left + (gScrollHThumbSize / 2); theValue = ((thePoint.h - thePin) * theRange) / theDistance; } else if ( hControl == ghVScrollBar) { // Scroll distance adjusted for scroll arrows and the thumb theDistance = rectControl.bottom - rectControl.top - gTotalVSizeAdjust; // Pin thePoint to the middle of the thumb thePin = rectControl.top + (gScrollVThumbSize / 2); theValue = ((thePoint.v - thePin) * theRange) / theDistance; } theValue += gValueSlop; return theValue; } // -------------------------------------------------------------------------- pascal void ProcScrollThumbAction (void) // handle thumb callbacks { Rect rectNull = {0, 0, 0, 0}; SInt32 theValue; WindowRef pWindow; ControlRef hControl = gControl; Point thePoint; Rect rectControl; pWindow = (*hControl)->contrlOwner; rectControl = (*hControl)->contrlRect; InsetRect (&rectControl, -kThumbTrackSlop, -kThumbTrackSlop); // expand control rect by tracking slop // Assumes the port is correctly set up GetMouse (&thePoint); if (PtInRect (thePoint, &rectControl)) theValue = CalcValueFromPoint (hControl, thePoint); // track new point point else theValue = gStartValue; // snap to start pos if (theValue != GetControlValue (hControl)) // if we scrolled { SetClip (gSaveClip); gSaveValue = theValue; MoveScroll (hControl, theValue - GetControlValue (hControl)); // move the scroll bar and check edges ScrollDrawContent (pWindow, GetControlValue (ghHScrollBar), GetControlValue (ghVScrollBar)); // draw stuff in window gSaveValue = GetControlValue (hControl); GetClip (gSaveClip); ClipRect (&rectNull); } } // -------------------------------------------------------------------------- OSErr BeginThumbTracking (ControlRef hControl) // start of thumb record values and save clip setting current clip to null { Rect rectNull = {0, 0, 0, 0}; OSErr theErr = noErr; Point thePoint; gControl = hControl; gStartValue = GetControlValue (hControl); gValueSlop = 0; GetMouse (&thePoint); gValueSlop = GetControlValue (hControl) - CalcValueFromPoint (hControl, thePoint); // delta from center gSaveClip = NewRgn (); GetClip (gSaveClip); ClipRect (&rectNull); return theErr; } // -------------------------------------------------------------------------- void DrawOneControlOffscreen (ControlHandle hControl) // draw a control into our offscreen port { GDHandle hGDSave; CGrafPtr pCGrafSave; Point ptSave; short i = (**hControl).contrlRfCon; GetGWorld (&pCGrafSave, &hGDSave); SetGWorld ((CGrafPtr) gpGWOffScreen, NULL); if (((gPtCntlPos [i].v) != (**hControl).contrlRect.top) || ((gPtCntlPos [i].h) != (**hControl).contrlRect.left)) { // reset control pos to original for offscreen update then restore it ptSave.v = (**hControl).contrlRect.top; ptSave.h = (**hControl).contrlRect.left; MoveControl (hControl, gPtCntlPos [i].h, gPtCntlPos [i].v); DrawControlInCurrentPort (hControl); // draw in offscreen MoveControl (hControl, ptSave.h, ptSave.v); } else // already in correct position DrawControlInCurrentPort (hControl); // draw in offscreen SetGWorld (pCGrafSave, hGDSave); } // -------------------------------------------------------------------------- void DoContentClick (WindowPtr pWindow, EventRecord * pEvent) { GrafPtr pPortSave = NULL; Point pointClick; short partWindow = 0; ControlHandle hControlHit = NULL; ControlActionUPP myActionUPP = NewControlActionProc (ProcScroll); ControlActionUPP myThumbUPP = NewControlActionProc (ProcScrollThumbAction); GetPort (&pPortSave); SetPort ((GrafPtr) pWindow); pointClick = pEvent->where; GlobalToLocal (&pointClick); partWindow = FindControl(pointClick, pWindow, &hControlHit); if ((hControlHit == ghHScrollBar) || (hControlHit == ghVScrollBar)) { gStartValue = GetControlValue (hControlHit); switch (partWindow) { case kControlIndicatorPart: // live scroll if ( BeginThumbTracking (hControlHit) == noErr ) { TrackControl ( hControlHit, pointClick, myThumbUPP); EndThumbTracking ( ); } break; case kControlUpButtonPart: // scroll up case kControlDownButtonPart: // scroll down case kControlPageUpPart: // page up case kControlPageDownPart: // page up partWindow = TrackControl (hControlHit, pointClick, myActionUPP); break; default: break; } if (hControlHit) { if (GetControlValue (hControlHit) - gStartValue) // if we really did move our scroll bar InvalRect (&pWindow->portRect); // generate a window update } } else if (hControlHit) { TrackControl(hControlHit, pointClick, (ControlActionUPP) -1); DrawOneControlOffscreen (hControlHit); // update our offscreen info } SetPort ((GrafPtr) pPortSave); } // -------------------------------------------------------------------------- void DoMenu (SInt32 menuResult) { SInt16 theMenu; SInt16 theItem; Str255 daName; MenuRef theMenuHandle; theMenu = HiWord(menuResult); theItem = LoWord(menuResult); theMenuHandle = GetMenuHandle(theMenu); switch (theMenu) { case kMenuApple: switch (theItem) { default: OpenDeskAcc(daName); break; } break; case kMenuFile: switch (theItem) { case kFileQuit: gDone = true; break; } break; } HiliteMenu(0); DrawMenuBar(); } // -------------------------------------------------------------------------- void DoEvent (void) { EventRecord theEvent; SInt16 whatPart; SInt32 menuResult; WindowPtr whichWindow; SInt8 theKey; SInt8 theCode; Rect rectGrow; long grow; if (WaitNextEvent(everyEvent, &theEvent, gSleepTime, NULL)) { switch (theEvent.what) { case mouseDown: whatPart = FindWindow(theEvent.where, &whichWindow); switch (whatPart) { case inGoAway: break; case inMenuBar: DrawMenuBar(); menuResult = MenuSelect(theEvent.where); if (HiWord(menuResult) != 0) DoMenu(menuResult); break; case inSysWindow: SystemClick(&theEvent, whichWindow); break; case inContent: if (whichWindow != FrontWindow ()) SelectWindow (whichWindow); else DoContentClick (whichWindow, &theEvent); break; case inDrag: DragWindow (whichWindow, theEvent.where, &(**LMGetGrayRgn()).rgnBBox); break; case inGrow: SetRect (&rectGrow, 100, 100, kOffScreenWidth + kScrollBarWidth, kOffScreenHeight + kScrollBarWidth); grow = GrowWindow (whichWindow, theEvent.where, &rectGrow); if (grow) { SizeWindow (whichWindow, grow & 0x0000FFFF, grow >> 16, true); SetScrollParams (whichWindow); // reset scroll limits AdjustScrollBar (gpWindow, ghVScrollBar); // adjust and draw scroll bars AdjustScrollBar (gpWindow, ghHScrollBar); SetPort (whichWindow); InvalRect (&whichWindow->portRect); // redraw all } break; } break; case keyDown: case autoKey: theKey = theEvent.message & charCodeMask; theCode = (theEvent.message & keyCodeMask) >> 8; if ((theEvent.modifiers & cmdKey) != 0) { menuResult = MenuKey(theKey); if (HiWord(menuResult) != 0) DoMenu (menuResult); } break; case updateEvt: BeginUpdate((WindowPtr) theEvent.message); DoUpdate((WindowPtr) theEvent.message); EndUpdate((WindowPtr) theEvent.message); break; case diskEvt: break; case osEvt: break; case kHighLevelEvent: AEProcessAppleEvent(&theEvent); break; } } else { // idle tasks } } // -------------------------------------------------------------------------- void DrawOffScreen (CGrafPtr pCGOffScreen) { GDHandle hGDSave; CGrafPtr pCGrafSave; Rect rectSource = (pCGOffScreen->portRect); RGBColor rgbGray = {0xC000, 0xC800, 0xD000}; short i; GetGWorld (&pCGrafSave, &hGDSave); SetGWorld (pCGOffScreen, NULL); // draw some background EraseRect (&rectSource); RGBForeColor (&rgbGray); PaintRect (&rectSource); MoveTo (rectSource.left, rectSource.top); LineTo (rectSource.right, rectSource.bottom); MoveTo (rectSource.right, rectSource.top); LineTo (rectSource.left, rectSource.bottom); // draw all my controls for (i = 0; i < kNumControls; i++) DrawControlInCurrentPort (ghControls[i]); // draw in offscreen (controls should not be scrolled here) SetGWorld (pCGrafSave, hGDSave); } // -------------------------------------------------------------------------- void SetScrollParams (WindowPtr pWindow) // set up scroll bars statics { short windowHeight = pWindow->portRect.bottom - pWindow->portRect.top; short windowWidth = pWindow->portRect.right - pWindow->portRect.left; gScrollVThumbSize = windowHeight * (windowHeight - kScrollBarWidthAdjust - kScrollArrowWidth * 2) / kOffScreenHeight; // thumb size based on relative size of window to offscreen gScrollHThumbSize = windowWidth * (windowWidth - kScrollBarWidthAdjust - kScrollArrowWidth * 2) / kOffScreenWidth; // thumb size based on relative size of window to offscreen gTotalVSizeAdjust = ((kScrollArrowWidth * 2) + gScrollVThumbSize); // amount that scroll bar is less than full height of window gTotalHSizeAdjust = ((kScrollArrowWidth * 2) + gScrollHThumbSize); // amount that scroll bar is less than full height of window } // -------------------------------------------------------------------------- void AdjustScrollBar (WindowPtr pWindow, ControlHandle scrollBar) // sets up scroll settings and thumb { short totalSize, viewSize; short windowHeight = pWindow->portRect.bottom - pWindow->portRect.top; short windowWidth = pWindow->portRect.right - pWindow->portRect.left; // get rect to determine if we are vert or horiz if (scrollBar == ghVScrollBar) { // vertical totalSize= kOffScreenHeight - (windowHeight - kScrollBarWidthAdjust); // total doc. height - visable doc viewSize= windowHeight + kScrollBarWidth; // vis. doc. height MoveControl (scrollBar, windowWidth - kScrollBarWidthAdjust, -1); SizeControl (scrollBar, kScrollBarWidth, windowHeight + 2 - kScrollBarWidthAdjust); } else { // horizontal totalSize= kOffScreenWidth - (windowWidth - kScrollBarWidthAdjust); // total doc. width - visable doc viewSize= windowWidth + kScrollBarWidth; // vis. doc. width MoveControl (scrollBar, -1, windowHeight - kScrollBarWidthAdjust); SizeControl (scrollBar, windowWidth + 2 - kScrollBarWidthAdjust, kScrollBarWidth); } // set the min, max, and current value of the scroll bar SetControl32BitMinimum (scrollBar, 0); SetControl32BitMaximum (scrollBar, totalSize); SetControl32BitValue (scrollBar, GetControlValue (scrollBar)); // set the scroll bar view size to create a proportional scroll box SetControlViewSize (scrollBar, viewSize); } // -------------------------------------------------------------------------- void InitToolbox(void) // standard inits { MenuHandle menu; SInt16 modifiers = 0; EventRecord event; MaxApplZone (); InitGraf((Ptr) &qd.thePort); InitFonts(); InitWindows(); InitMenus(); TEInit(); InitDialogs(nil); InitCursor(); qd.randSeed = TickCount(); // init events EventAvail(everyEvent, &event); modifiers |= event.modifiers; EventAvail(everyEvent, &event); modifiers |= event.modifiers; EventAvail(everyEvent, &event); modifiers |= event.modifiers; // Init Menus menu = NewMenu (kMenuApple, "\p\024"); // new apple menu InsertMenu (menu, 0); // add menu to end AppendResMenu(menu, 'DRVR'); menu = NewMenu (kMenuFile, "\pFile"); // new menu InsertMenu (menu, 0); // add menu to end AppendMenu (menu, "\pQuit/Q"); // add items DrawMenuBar(); } // -------------------------------------------------------------------------- Boolean SetUp (void) // set up windows, controls, off screen { short i; MenuHandle hMenu; Rect rectSize; InitToolbox (); SetRect (&gRectWindowGbl, 0, 0, kWindowWidth, kWindowHeight); OffsetRect (&gRectWindowGbl, kWindowOffset, kWindowOffset); gpWindow = NewCWindow (NULL, &gRectWindowGbl, "\pControl Scroll Test", false, kWindowGrowDocumentProc, (WindowPtr) -1, false, 0); SetScrollParams (gpWindow); SetRect (&rectSize, -1, kWindowHeight - kScrollBarWidthAdjust, kWindowWidth + 1 - kScrollBarWidthAdjust, kWindowHeight + 1); ghHScrollBar = NewControl (gpWindow, &rectSize, "\p", false, 0, 0, 0, kControlScrollBarProc, 0); if (!ghHScrollBar) return false; AdjustScrollBar (gpWindow, ghHScrollBar); ShowControl (ghHScrollBar); SetRect (&rectSize, kWindowWidth - kScrollBarWidthAdjust, -1, kWindowWidth + 1, kWindowHeight + 1 - kScrollBarWidthAdjust); ghVScrollBar = NewControl (gpWindow, &rectSize, "\p", false, 0, 0, 0, kControlScrollBarProc, 0); if (!ghVScrollBar) return false; AdjustScrollBar (gpWindow, ghVScrollBar); ShowControl (ghVScrollBar); hMenu = NewMenu (kButtonMenuID, "\pButton"); // new menu AppendMenu (hMenu, "\pItem 1;Item 2;Item 3;Item 4"); // add items InsertMenu (hMenu, hierMenu); // add menu to end for (i = 0; i < kNumControls; i++) { short top = 10 + (abs (Random ()) % (kOffScreenHeight - kScrollBarWidth - 10 - 20)); short left = 10 + (abs (Random ()) % (kOffScreenWidth - kScrollBarWidth - 10 - 75)); SetRect (&rectSize, left, top, left + 75, top + 20); // NOTE: intial pos is stored in gPtCntlPos array to allow reference during scrolling ghControls [i] = NewControl (gpWindow, &rectSize, "\p", true, 0, kButtonMenuID, 0, popupMenuProc, i); if (!(ghControls [i])) return false; gPtCntlPos [i].v = rectSize.top; gPtCntlPos [i].h = rectSize.left; } SetRect (&rectSize, 0, 0, kOffScreenWidth, kOffScreenHeight); if (NewGWorld (&gpGWOffScreen, 32, &rectSize, NULL, NULL, 0) != noErr) return false; DrawOffScreen ((CGrafPtr) gpGWOffScreen); ShowWindow (gpWindow); return true; } // functions (external/public) ----------------------- ---------------------- int main (void) { if (SetUp ()) while (!gDone) DoEvent (); CleanUp (); return 0; }